/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 *///
package Client;

import Shared.ClientInt;
import Shared.Message;
import java.rmi.AccessException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.logging.Level;
import java.util.logging.Logger;
import Shared.ServerInt;
import Shared.User;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import static java.lang.System.out;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
import javax.management.Notification;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import sun.misc.IOUtils;
//

/**
 *
 * @author belal
 */
public class ClientImp extends UnicastRemoteObject implements ClientInt {

    ServerInt serverRef;
    User meUser;
    User friendUser;
    private ArrayList<User> friends = new ArrayList<>();
    static HashMap<String, ChatWonePerson> ChatOpen = new HashMap<>();
    static HashMap<String, ConversationGui> ChatGroupOpen = new HashMap<>();
    static HashMap<String, MainForm> mainFormMap = new HashMap<>();
    BufferedOutputStream out;
    public ClientImp() throws RemoteException {
        try {
            Registry reg = LocateRegistry.getRegistry("127.0.0.1", 5005);
            serverRef = (ServerInt) reg.lookup("ChattingService");
        } catch (NotBoundException ex) {
            System.out.println("Server is idle");
            System.exit(0);
        } catch (AccessException ex) {
            System.out.println("Server is idle");
            System.exit(0);
        }
        this.updateFriendList();
    }

    public void removeChatOpen(String ident) {
        ChatOpen.remove(ident);
    }

    @Override
    public void changeStatus(ArrayList<String> mails, String mail, String userName, String status,int statusNo) {
        ArrayList<ClientInt> myFreinds = null;
        try {
            myFreinds = serverRef.getMyFriends(mails);
            serverRef.changeStatus(mail, statusNo);
        } catch (RemoteException ex) {
            NotificationForm note = new NotificationForm("Good Bye");
        }
        if (!(myFreinds.isEmpty())) {
            for (ClientInt cli : myFreinds) {
                if (cli != null) {
                    try {
                        cli.notifyMyFriend(userName, status);
                    } catch (RemoteException ex) {
                       // NotificationForm note = new NotificationForm("Good Bye");
                    }
                } else {
                   
                }
            } 
        }

    }

    @Override
    public void notifyMyFriend(String mail, String status) throws RemoteException {
        NotificationForm nForm = new NotificationForm(mail, status);
        this.updateFriendList();
    }

    public User getUser(String mail) {
        User u = null;
        Iterator<User> i = friends.iterator();
        while (i.hasNext()) {
            u = i.next();
            if (u.getUserMail().equalsIgnoreCase(mail)) {
                System.out.println(u.getUserMail());
            }
        }
        return u;
    }

    @Override
    public int signupUser(User user) {
        //System.out.println(user.getUserFName());
        int returnval = 0;
        try {
            returnval = serverRef.registerUser(user);
        } catch (Exception e) {
            System.out.println("client sign up");
            e.printStackTrace();
        }
        System.out.println(returnval);
        return returnval;
    }

    @Override
    public ArrayList<User> signinUser(User user) {
        int retVal = 0;
        
        try {
            friends = serverRef.loginUser(user, this);
        } catch (RemoteException ex) {
            ex.printStackTrace();
        }
        return friends;
    }

    @Override
    public void checkFriendRequest(String mail) throws RemoteException {
        ArrayList<User> sender = new ArrayList<>();
        ArrayList<User> friList = new ArrayList<>();
        sender = serverRef.CheckFriendRequests(mail);
        System.out.println(sender.toString());
        for (int i = 0; i < sender.size(); i++) {
            int returnVal = getFriendRequestNotify(sender.get(i));
            if (returnVal >=1) {
                friList = serverRef.updateFriendRequest(sender.get(i).getUserMail(), mail);
                this.updateFriendList();
            }
        }
    }
      @Override
    public void updateFriendList() throws RemoteException {
        //ArrayList<User>frArrayList=null;
        for (Map.Entry<String,MainForm> entry :mainFormMap.entrySet()) {
            entry.getValue().addFriend();
        }
    }

    
    @Override
    public void updateFormlist(){
        for (Map.Entry<String,MainForm > entry :mainFormMap.entrySet()) {
            entry.getValue().addFriend();
        }
    }
    @Override
    public void addFriend(User sender,String reciever) throws RemoteException {
        int retVal=serverRef.addFreind(sender,reciever);
        if(retVal==1){
            this.updateFormlist();
        }
    }

    @Override
    public void sendMail() throws RemoteException {
    }

    @Override
    public void sendFile() throws RemoteException {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    public void setMainForm(String mail, MainForm mf) {
        mainFormMap.put(mail, mf);
    }

    @Override
    public void removeMainForm(String mail) throws RemoteException{
        if (mainFormMap.containsKey(mail)) {
            MainForm mf = mainFormMap.get(mail);
            mf.dispose();
        }
    }

    @Override
    public void recieveMessage(String message, String ident, User friendUser, User meUser) throws RemoteException {
        int index = ident.indexOf(":");
        String Str1 = ident.substring(0, index);
        String Str2 = ident.substring(index + 1, ident.length());
        String ident1 = Str2 + ":" + Str1;
        checkIdent(ident1, meUser, friendUser).receiveMessageInTextArea(message);
    }

    @Override
    public void recieveGroupMessage(String message, String ident, User[] friends, ArrayList<String> friendsmail, String user) throws RemoteException {
        checkIdentGroupChat(ident, friends, friendsmail, user).receiveMessageInTextArea(message);
    }

    public ChatWonePerson checkIdent(String ident, User meUser, User friendUser) {
        ChatWonePerson form = null;
        this.meUser = meUser;
        this.friendUser = friendUser;
        //System.out.println("in checkIdent \n meUser:"+meUser.getUserMail()+"\n friendUser:"+friendUser.getUserMail());
        int index = ident.indexOf(":");
        String Str1 = ident.substring(0, index);
        String Str2 = ident.substring(index + 1, ident.length());
        String ident1 = Str2 + ":" + Str1;
        System.out.println(ident1);
        if (ChatOpen.containsKey(ident) || ChatOpen.containsKey(ident1)) {
            form = ChatOpen.get(ident);
            form.setFocusable(true);
        } else {
            try {
                ClientInt cli = serverRef.chatFreind(Str2);
                form = new ChatWonePerson(cli, ident, meUser, friendUser);
                ChatOpen.put(ident, form);
                form.setVisible(true);
            } catch (RemoteException ex) {
                Logger.getLogger(ClientImp.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
        return form;

    }

    public ArrayList<ClientInt> getChatGroupClient(ArrayList<String> mails) {
        ArrayList<ClientInt> client = new ArrayList<>();
        try {
            client = serverRef.StartChatGroup(mails);
        } catch (RemoteException ex) {
            ex.printStackTrace();
        }
        return client;
    }

    public ConversationGui checkIdentGroupChat(String ident, User[] friendsArray, ArrayList<String> friendsMail, String user) {
        ConversationGui form = null;
        ArrayList<ClientInt> group = null;
        if (ChatGroupOpen.containsKey(ident)) {
            form = ChatGroupOpen.get(ident);
            form.setFocusable(true);
        } else {
            group = getChatGroupClient(friendsMail);
            form = new ConversationGui(group, ident, friendsArray, friendsMail, user);
            ChatGroupOpen.put(ident, form);
            form.setVisible(true);
        }
        return form;
    }

    @Override
    public int getFriendRequestNotify(User sender) throws RemoteException {
        int returnVal = 0;
        NotificationForm note = new NotificationForm();
        returnVal = note.recieveFriendRequest(sender);
        return returnVal;
    }

    @Override
    public ArrayList<User> getFriendList() throws RemoteException {
        return friends;
    }

    @Override
    public void signOut(String mail) {
        //int returnval=0;
        try {
            if (mainFormMap.containsKey(mail)) {
                mainFormMap.remove(mail);
            }
            serverRef.signOut(mail);
        } catch (RemoteException ex) {
            NotificationForm note = new NotificationForm("Good Bye");
        }
    }

    @Override
    public void interactiveMessage(String message, String ident, User friendUser, User meUser) throws RemoteException {
        int index = ident.indexOf(":");
        String Str1 = ident.substring(0, index);
        String Str2 = ident.substring(index + 1, ident.length());
        String ident1 = Str2 + ":" + Str1;
        checkIdent(ident1, meUser, friendUser).interactiveMessageInTextField(message);
    }

    @Override
    public void notifyFromServer(String msg) throws RemoteException {
        NotificationForm nForm = new NotificationForm(msg);
    }

    @Override
    public void stopServer(String msg) throws RemoteException {
        NotificationForm nForm = new NotificationForm(msg);
        for (Map.Entry<String, ChatWonePerson> entry : ChatOpen.entrySet()) {
            entry.getValue().dispose();
        }
        ChatOpen.clear();
        for (Map.Entry<String, ConversationGui> entry : ChatGroupOpen.entrySet()) {
            entry.getValue().dispose();
        }
        ChatGroupOpen.clear();
        for (Map.Entry<String,MainForm > entry :mainFormMap.entrySet()) {
            entry.getValue().dispose();
        }
        mainFormMap.clear();
    }

  

    @Override
    public void reciveFile(byte[] bytes) throws RemoteException, IOException {
       // byte[] bytes = buff.toByteArray();
      out.write(bytes);
                
              System.out.println("reciving..");
                  out.flush();
                
        }
    @Override
    public void reciveFileend() throws RemoteException {
        try {
            System.out.println("i am finished");
            out.close();
        } catch (IOException ex) {
            Logger.getLogger(ClientImp.class.getName()).log(Level.SEVERE, null, ex);
        }
                JOptionPane.showMessageDialog(null, "file is downloades successfully","Finished",JOptionPane.OK_OPTION);
    
        }


    @Override
    public void reciveFilename(String name) throws RemoteException {
          if (JOptionPane.showConfirmDialog(null, "you have recived an attachement file do you want to accept it?", "WARNING",
                JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
         StringBuffer strb = new StringBuffer(System.getProperty("user.home"));
         strb.append("/" + name);
         String xx = (strb.toString());
         File f= new File(xx);
         try {
             out=new BufferedOutputStream(new FileOutputStream(f));
         } catch (FileNotFoundException ex) {
             Logger.getLogger(ClientImp.class.getName()).log(Level.SEVERE, null, ex);
         }
        
    }
    }

    @Override
    public void sendFile(FileInputStream fis, String path, String name) throws RemoteException {
       BufferedReader bufferedReader = null;
    }

    @Override
    public boolean chatFriend(String mail) throws RemoteException {
        boolean returnVal=false;
        ClientInt cli= serverRef.chatFreind(mail);
        if(cli !=null){
            returnVal=true;
        }else{
            returnVal=false;
        }
        return returnVal;
    }

}
